#include "MCSelectController.h"
#include <MCUtils.h>
#include <MCSettings.h>
#include <ICanvas.h>
#include <IGraphicsItem.h>
#include <iostream>
#include <MCConstraintVisual.h>
#include <MCGripPoint.h>

MCSelectController::MCSelectController(ICanvas *presenter) :
    _presenter(presenter),
    _mouseMoved(false)
{
}

void MCSelectController::onMouseDown(IMouseArgs &args)
{
    _mouseMoved = false;
}

void MCSelectController::onMouseUp(IMouseArgs &args)
{
    if (_mouseMoved == false)
    {
        IGraphicsItem *item = _presenter->itemAt(args.position());

        if (auto grip = _presenter->gripAt(args.position()))
        {
            item = dynamic_cast<MCGraphicsItem *>(grip);
        }

        if (args.isLeftMousePressed())
        {
            if (args.isCtrlPressed())
            {
                addSelection(item);
            }
            else
            {
                deselectAll();
                addSelection(item);
            }
        }
        else if (args.isRightMousePressed())
        {
            deselectAll();
        }
    }
}

void MCSelectController::onMouseMove(IMouseArgs &args)
{
    _mouseMoved = true;

    if (IGraphicsItem *item = _presenter->itemAt(args.position()))
    {
        unhoverAll();
        if (item->isSelected() == false)
            item->hoverEnter();
    }
    else
    {
        unhoverAll();
    }
}

void MCSelectController::onKeyDown(IKeyArgs &args)
{
    if (args.key() == MCSettings::TerminateKey)
    {
        deselectAll();
    }
    else if (args.key() == MCSettings::DeleteKey)
    {
        deleteSelections();
    }
}

const std::vector<IGraphicsItem *> &MCSelectController::selections()
{
    return _selections;
}

const std::vector<MCGripPoint *> &MCSelectController::selectedGripPoints()
{
    return _selectedGrips;
}

void MCSelectController::addSelection(IGraphicsItem *item)
{
    if (item != nullptr)
    {
        if (item->isSelected() == false)
        {
            if (auto grip = dynamic_cast<MCGripPoint *>(item))
            {
                _selectedGrips.push_back(grip);
            }
            else
            {
                _selections.push_back(item);
            }
         
            item->select();
        }
        else
        {
            if (MCGripPoint *grip = dynamic_cast<MCGripPoint *>(item))
            {
                _selectedGrips.erase(std::remove(_selectedGrips.begin(), _selectedGrips.end(), item), _selectedGrips.end());
            }
            else
            {
                removeFromSelections(item);
            }

            item->deselect();
        }
    }
}

void MCSelectController::removeFromSelections(IGraphicsItem *item)
{
    MCUtils::RemoveFromVector(_selections, item);
}

void MCSelectController::deselectAll()
{
    for (IGraphicsItem *item : _selections)
    {
        item->deselect();
    }

    for (MCGripPoint *grip : _selectedGrips)
    {
        grip->deselect();
    }

    _selections.clear();
    _selectedGrips.clear();
}

void MCSelectController::deleteSelections()
{
    for (size_t i = 0; i < _selections.size(); i++)
    {
        if (auto c = dynamic_cast<MCConstraintVisual *>(_selections[i]))
        {
            _presenter->constraintManager()->removeConstraint(c->constraint);
        }

        _presenter->removeVisualItem(_selections[i]);
    }

    _selections.clear();
}

void MCSelectController::unhoverAll()
{
    for (size_t i = 0; i < _presenter->items().size(); i++)
    {
        if (_presenter->items()[i]->isSelected() == false)
            _presenter->items()[i]->hoverLeave();
    }
}
